package io.chenglicun.modules.check.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.chenglicun.common.entity.BaseEntity;
import io.chenglicun.common.page.PageData;
import io.chenglicun.common.service.impl.CrudServiceImpl;
import io.chenglicun.common.constant.Constant;
import io.chenglicun.modules.check.dao.ClcCheckDao;
import io.chenglicun.modules.check.dto.ClcCheckDTO;
import io.chenglicun.modules.check.dto.ClcCheckDetailDTO;
import io.chenglicun.modules.check.entity.ClcCheckEntity;
import io.chenglicun.modules.check.service.ClcCheckDetailService;
import io.chenglicun.modules.check.service.ClcCheckService;
import io.chenglicun.modules.clc.dto.ClcUserDeptDTO;
import io.chenglicun.modules.clc.service.ClcUserDeptService;
import io.chenglicun.modules.evaluation.dao.ClcEvaluationDao;
import io.chenglicun.modules.evaluation.dao.ClcEvaluationTemplateDao;
import io.chenglicun.modules.evaluation.entity.ClcEvaluationEntity;
import io.chenglicun.modules.evaluation.entity.ClcEvaluationTemplateEntity;
import io.chenglicun.modules.security.user.SecurityUser;
import io.chenglicun.modules.sys.dao.SysDeptDao;
import io.chenglicun.modules.sys.dao.SysUserDao;
import io.chenglicun.modules.sys.entity.SysDeptEntity;
import io.chenglicun.modules.sys.entity.SysUserEntity;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 考核
 *
 * @author HB 137664951@qq.com
 * @since 1.0 2023-11-29
 */
@Service
public class ClcCheckServiceImpl extends CrudServiceImpl<ClcCheckDao, ClcCheckEntity, ClcCheckDTO> implements ClcCheckService {

    @Autowired
    private ClcEvaluationDao evaluationDao;
    @Autowired
    private SysUserDao userDao;
    @Autowired
    private SysDeptDao deptDao;
    @Autowired
    private ClcEvaluationTemplateDao templateDao;
    @Autowired
    private ClcUserDeptService userDeptService;
    @Autowired
    private ClcCheckDetailService detailService;

    @Override
    public QueryWrapper<ClcCheckEntity> getWrapper(Map<String, Object> params){
        QueryWrapper<ClcCheckEntity> wrapper = new QueryWrapper<>();

        Object evaluationId = params.get("evaluationId");
        Object userDeptId = params.get("userDeptId");
        Object userId = params.get("userId");
        Object deptId = params.get("deptId");
        wrapper.eq(ObjectUtil.isNotEmpty(evaluationId), "evaluation_id", evaluationId);
        wrapper.eq(ObjectUtil.isNotEmpty(userDeptId), "user_dept_id", userDeptId);
        wrapper.eq(ObjectUtil.isNotEmpty(userId), "user_id", userId);
        wrapper.eq(ObjectUtil.isNotEmpty(deptId), "dept_id", deptId);

        return wrapper;
    }

    @Override
    public PageData<ClcCheckDTO> page(Map<String, Object> params) {
        PageData<ClcCheckDTO> page = super.page(params);
        List<ClcCheckDTO> list = page.getList();

        this.setData(list.toArray(new ClcCheckDTO[0]));

        return page;
    }

    @Override
    public List<ClcCheckDTO> list(Map<String, Object> params) {
        List<ClcCheckDTO> list = super.list(params);

        this.setData(list.toArray(new ClcCheckDTO[0]));

        return list;
    }

    @Override
    public ClcCheckDTO get(Long id) {
        ClcCheckDTO dto = super.get(id);

        this.setData(dto);

        return dto;
    }

    private void setData(ClcCheckDTO... dtos) {
        if (dtos == null || dtos.length == 0) return;

        List<Long> evaluationIds = Arrays.stream(dtos).map(ClcCheckDTO::getEvaluationId).filter(Objects::nonNull).collect(Collectors.toList());
        List<Long> userIds = Arrays.stream(dtos).map(ClcCheckDTO::getUserId).filter(Objects::nonNull).collect(Collectors.toList());
        List<Long> deptIds = Arrays.stream(dtos).map(ClcCheckDTO::getDeptId).filter(Objects::nonNull).collect(Collectors.toList());
        Long[] ids = Arrays.stream(dtos).map(ClcCheckDTO::getId).filter(Objects::nonNull).toArray(Long[]::new);

        List<ClcEvaluationEntity> evaluationEntities = evaluationIds.size() == 0 ? new ArrayList<>() :
                evaluationDao.selectList(new QueryWrapper<ClcEvaluationEntity>().lambda().in(BaseEntity::getId, evaluationIds));
        List<SysUserEntity> userEntities = userIds.size() == 0 ? new ArrayList<>() :
                userDao.selectList(new QueryWrapper<SysUserEntity>().lambda().in(BaseEntity::getId, userIds));
        List<SysDeptEntity> deptEntities = deptIds.size() == 0 ? new ArrayList<>() :
                deptDao.selectList(new QueryWrapper<SysDeptEntity>().lambda().in(BaseEntity::getId, deptIds));
        List<ClcCheckDetailDTO> detailList = ids.length == 0 ? new ArrayList<>() : detailService.getByCheckIds(ids);

        for (ClcCheckDTO dto : dtos) {
            if (dto != null) {
                dto.setEvaluationName(
                        evaluationEntities.stream().filter(t -> t.getId().equals(dto.getEvaluationId())).map(ClcEvaluationEntity::getName).findFirst().orElse(null)
                );
                dto.setUserName(
                        userEntities.stream().filter(t -> t.getId().equals(dto.getUserId())).map(SysUserEntity::getRealName).findFirst().orElse(null)
                );
                dto.setDeptName(
                        deptEntities.stream().filter(t -> t.getId().equals(dto.getDeptId())).map(SysDeptEntity::getName).findFirst().orElse(null)
                );
                dto.setDetailList(
                        detailList.stream().filter(t -> t.getCheckId().equals(dto.getId())).collect(Collectors.toList())
                );
            }
        }

    }

    @Override
    @Transactional
    public void save(ClcCheckDTO dto) {
        ClcUserDeptDTO userDeptDTO = userDeptService.get(dto.getUserDeptId());
        dto.setUserId(userDeptDTO.getUserId());
        dto.setDeptId(userDeptDTO.getDeptId());

        super.save(dto);

        List<ClcCheckDetailDTO> detailList = dto.getDetailList();
        detailList.forEach(t -> t.setCheckId(dto.getId()));

        detailService.saveBatch(detailList);
        int sum = detailList.stream().mapToInt(ClcCheckDetailDTO::getScore).sum();

        ClcEvaluationTemplateEntity templateEntity = templateDao.selectById(dto.getTemplateId());
        dto.setScore(templateEntity.getScore() + sum);
        super.update(dto);
    }

    @Override
    @Transactional
    public void update(ClcCheckDTO dto) {
        ClcUserDeptDTO userDeptDTO = userDeptService.get(dto.getUserDeptId());
        dto.setUserId(userDeptDTO.getUserId());
        dto.setDeptId(userDeptDTO.getDeptId());

        detailService.deleteByCheckIds(dto.getId());

        List<ClcCheckDetailDTO> detailList = dto.getDetailList();
        detailList.forEach(t -> t.setCheckId(dto.getId()));

        detailService.saveBatch(detailList);
        int sum = detailList.stream().mapToInt(ClcCheckDetailDTO::getScore).sum();

        ClcEvaluationTemplateEntity templateEntity = templateDao.selectById(dto.getTemplateId());
        dto.setScore(templateEntity.getScore() + sum);
        super.update(dto);
    }

    @Override
    @Transactional
    public void delete(Long[] ids) {
        super.delete(ids);

        detailService.deleteByCheckIds(ids);
    }
}